#ifndef REGIONMAP_H
#define REGIONMAP_H

#ifdef CLIENT
class ClientWorld;
#endif
#include "MainHeader.h"

#include <map>

using namespace std;

struct Position {
	/* XZ-Position */
	int x;
	int z;

#ifndef MULTILOAD
	bool loaded;
#endif

	Position() {
		x		= 0;
		z		= 0;
#ifndef MULTILOAD
		loaded = false;
#endif
	};
	Position(int _x, int _z) {
		x		= _x;
		z		= _z;
#ifndef MULTILOAD
		loaded = true;
#endif
	};

	bool operator == (const Position& rhs) const
	{
#ifndef MULTILOAD
		return ((x == rhs.x) && (z == rhs.z) && loaded);
#else
		return ((x == rhs.x) && (z == rhs.z));
#endif
	};
	bool operator < (const  Position& rhs) const
	{
		return (( z < rhs.z) || ( z == rhs.z) && (( x < rhs.x)));
	};
	bool operator > (const  Position& rhs) const
	{
		return  (( z > rhs.z) || ( z == rhs.z) && (( x > rhs.x)));
	};
};

struct Regioncombound {
	/* Region */
	Region*		region;

	/* Count for how many times the Region is opened */
	WORD		count;
	/* Count for how many times the Chunks of the Region are opened */
	DWORD		countChunks;
	BYTE		loadedCunks[256];
	SRWLOCK		LOCK;

	Regioncombound();
	Regioncombound(Region * _region);
	bool subtract();
	void add();
	bool subtract(BYTE _x, BYTE _z);
	void add(BYTE _x, BYTE _z);
	BYTE getLoadedChunks(BYTE _x, BYTE _z);
};


typedef pair<Position, Regioncombound> Region_type;
class Regionmap {
protected:
#ifdef MULTILOAD
	map<Position, Regioncombound>	m_map;
	SRWLOCK							LOCK;
#else
	bool							m_loadFiles;
	int								m_size;
	Region **						m_map;
	Position *						m_pos;
#endif
public:
	Regionmap(bool loadFiles = true);
	~Regionmap();
	size_t size();
	Region * getRegion(int x, int z);
	Region * getValue(int i);
	Region * removeRegion(int x, int z);
	Region * insertRegion(Region * region, int x, int z);
	virtual Region * createRegion(IWorld* world, int seed, int x, int z);

	/* Load if True returns */
	virtual int loadChunk(int x, int z, BYTE ix, BYTE iz);

	/* Unloaded if True returns */
	Region * unloadChunk(int x, int z, BYTE ix, BYTE iz, Chunk ** chunks);
};

#ifdef CLIENT
class ClientRegionmap : public Regionmap {
private:
	ClientWorld * m_pWorld;
public:
	ClientRegionmap(ClientWorld * pWorld, bool loadFiles);

	Region * createRegion(ClientWorld * world, int seed, int x, int z);
	int loadChunk(int x, int z, BYTE ix, BYTE iz);
};
#endif

#endif